"""
服务端主架构
"""
from calc import *
import socket, json
import logging as log
from time import sleep
from threading import Thread, Event, active_count
ip, port = "127.0.0.1", 1046
log.basicConfig(format='%(asctime)s %(message)s',datefmt="%m-%d %H:%M:%S",level=log.INFO)
http=["OPTIONS","GET","HEAD","POST","PUT","DELETE","TRACE","CONNECT"]
answer_nums, turns, statu = 0, 0, False
I_lock, C_lock, G_lock = Event(), Event(), Event()
result, names, players, users = dict(), list(), list(), list()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((ip, port))
sock.listen(2)
log.info("start")
def wait_data(name):
    global answer_nums, users, turns, result, statu, players
    C_lock.clear()
    turns += 1
    log.info("turn %d %s",turns,users)
    for i in range(40):
        if answer_nums==len(users) or len(users)==0:
            break
        sleep(0.5)
    result, statu = calc(turns)
    log.debug("resu %s %s",name,result)
    if statu:
        players = list()
        I_lock.set()
        log.debug("over %s %s",name,players)
    answer_nums, users = 0, list()
    C_lock.set()
def handle(connection, address):
    global answer_nums, users, turns, names, players
    try:
        connection.settimeout(20)
        while True:
            name = connection.recv(1024).decode()
            violations = [i for i in http if i in name]
            if len(violations) > 0:
                connection.close()
                log.debug("http %s %s",address,violations)
                return
            elif name in names:
                connection.send(b"\x01")
            else:
                names.append(name);break
        log.info("conn %s %s",name,names)
    except Exception as error:
        log.info("test %s %s",address,error)
        return
    try:
        while True:
            if len(players) == 0:
                I_lock.set()
            else:
                I_lock.wait()
            players.append(name)
            if players[0] == name:
                turns = 0
                try:
                    connection.send(b"\x00")
                    connection.recv(1024)
                finally:
                    G_lock.set()
                    I_lock.clear()
                    log.info("game %s",players)
            else:
                G_lock.wait()
            connection.send(json.dumps(players).encode())
            if G_lock.is_set():
                G_lock.clear()
            while True:
                users.append(name)
                if users[0] == name:
                    Thread(target=wait_data,args=(name,)).start()
                data = json.loads(connection.recv(1024).decode())
                log.debug("recv %s %s %d",name,data,answer_nums)
                answer_nums += 1
                add(name, data)
                C_lock.wait()
                connection.sendall(json.dumps(result).encode())
                if statu:
                    break
            statu_a = connection.recv(1024)
            if statu_a == b"\x01":continue
            elif statu_a == b"\x02":break
    except TimeoutError:
        connection.close()
        if name in players:
            players.remove(name)
        if name in users:
            users.remove(name)
        log.debug("clos %s %s %s",name,players,users)
    except Exception as error:
        if name in players:
            players.remove(name)
        if name in users:
            users.remove(name)
        log.debug("erro %s %s %s %s %s",name,players,users,type(error),error)
    else:
        log.info("exit %s",name)
    finally:
        names.remove(name)
while active_count() < 30:
    Thread(target=handle,args=sock.accept()).start()
log.info("stopped")